Skip to content

perf: cache WAL resume state on Pager to skip per-flush rescan (#640) - #642

Merged
iheitlager merged 1 commit into
mainfrom
perf/640-wal-resume-cache
Aug 29, 2026
Merged

perf: cache WAL resume state on Pager to skip per-flush rescan (#640)#642
iheitlager merged 1 commit into
mainfrom
perf/640-wal-resume-cache

Conversation

@iheitlager

Copy link
Copy Markdown
Member

Summary

Follow-up from #635/#640. WalWriter::open_existing (src/pager/wal.rs) re-read and rescanned the entire -wal file on every commit — ADR-0026's accepted trade-off, measured at ~6-7ms per commit even against a near-empty WAL file.

Caches a small WalResumeHint (header, offset, running checksum, expected file size) on Pager, mirroring the existing wal_shm handle cache (#437):

  • Populated after every successful WalWriter::sync.
  • Reset to None at the same three sites wal_shm already resets at: switch_wal_to_journal, switch_journal_to_wal, recreate_wal_locked.
  • WalWriter::open_existing only trusts the hint when the file's actual size and a cheap 32-byte header re-read both match — any mismatch (concurrent writer, mode switch, torn file from a crash) falls back to exactly the original full read + rescan, so correctness never depends on the cache being right, only commit latency does.

Adds .openspec/adr/0035-wal-resume-hint-cache-supersedes-0026.md superseding ADR-0026's rejected caching alternative, since ADR-0026 predicted and is directly cited by this ticket.

spend: matched estimate (~Medium, well under the 200-350k token budget)

Test plan

  • flush_wal_mode_second_commit_resumes_correctly_from_cached_hint — consecutive commits from the same Pager stay correct once the second resumes from the cache.
  • flush_wal_mode_after_mode_round_trip_does_not_reuse_stale_hint — WAL→Legacy→WAL round trip invalidates the cache and still commits correctly.
  • flush_wal_mode_falls_back_to_rescan_when_wal_grew_from_elsewhere — a second Pager writer's commit is not corrupted by the first Pager's stale cached hint.
  • All existing pager/wal unit tests pass unchanged (80 tests).
  • Full cargo test suite passes.
  • make lint (clippy + fmt) clean.

Closes #640


🤖 Analysis by Claude

WalWriter::open_existing re-read and rescanned the entire -wal file on
every commit (ADR-0026's accepted trade-off), measured at ~6-7ms per
commit even against a near-empty WAL (#635's profiling). Cache a small
WalResumeHint (header, offset, running checksum, expected file size) on
Pager, refreshed after each flush and invalidated at the same three
sites the existing wal_shm handle cache (#437) already resets at
(switch_wal_to_journal, switch_journal_to_wal, recreate_wal_locked).
open_existing trusts the hint only when the file's actual size and a
cheap header re-read both still match, so a concurrent writer, mode
switch, or torn file always falls back to the original full rescan.

Supersedes ADR-0026's rejected caching alternative with ADR-0035, since
0026 is cited by this ticket.

spend: matched estimate (~Medium)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@iheitlager
iheitlager merged commit 0ac473d into main Aug 29, 2026
6 checks passed
@iheitlager
iheitlager deleted the perf/640-wal-resume-cache branch August 29, 2026 13:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

perf: WAL commit re-reads and rescans the entire -wal file every flush (ADR-0026 debt)

1 participant